package com.lz.type.example;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * TypeDemo..
 *
 * 目的获取泛型参数T
 *
 * @author Lizhong
 * @date 2020/3/23
 */
public class TypeDemo<T> {

    T newInstance(T t) {
        // new 一个T我们得不到T的类型


        return t;
    }

    /**
     * 第一种思路，显示指定 t的类型参数
     * @param t
     * @return
     */
    T newInstance(Class<T> t) {
        // new 一个T我们得不到T的类型
        try {
            return (T) t.getConstructors()[0].newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        return null;
    }


    public static void main(String[] args) {
        TypeDemoChild typeDemoChild = new TypeDemoChild();
        Object o = typeDemoChild.newInstance();
        System.out.println(o.getClass());
    }
}

/**
 * 第二种思路
 */
@Slf4j
class TypeDemoChild extends TypeDemo<String> {
    Object newInstance() {
        Type type = null;
        ParameterizedType genericSuperclassType = (ParameterizedType) TypeDemoChild.class.getGenericSuperclass();
        if (genericSuperclassType instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) genericSuperclassType).getActualTypeArguments();
            type = actualTypeArguments[0];
            for (Type argumentType : actualTypeArguments) {
                log.info("父类ParameterizedType.getActualTypeArguments:" + argumentType);
            }
        }

        String aClass = type.getTypeName();
        try {
            Class<?> aClass1 = Class.forName(aClass);
            return ((Class)type).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }


        return null;
    }
}